﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;
using System.Web.Mvc;
using System.Web;
using System.IO;
using System.Reflection;

namespace MVCPlugin.Utility
{
    internal class PluginActionUrlRoute : LocalizedRoute
    {
        public PluginActionUrlRoute()
            : base("plugin/{plugin}/{controller}/{action}/{id}", new RouteValueDictionary(new { controller = "Home", action = "Index", id = UrlParameter.Optional }), new MvcRouteHandler())
        {
            DataTokens = new RouteValueDictionary();
            DataTokens["UseNamespaceFallback"] = false;
        }

        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            RouteData data = base.GetRouteData(httpContext);
            if (data == null)
            {
                return null;
            }
            string pluginName = data.Values["plugin"] as string;
            string controllerName = data.Values["controller"] as string;
            string actionName = data.Values["action"] as string;
            PluginMetadata meta = Plugin.GetPluginMetadata(pluginName);
            if (meta == null || meta.Status != PluginStatus.Installed)
            {
                return null;
            }
            string ns = string.IsNullOrWhiteSpace(meta.MvcControllerNamespace) ? pluginName + ".*"
                : meta.MvcControllerNamespace.Trim();
            data.DataTokens["Namespaces"] = new string[] { ns };
            TempControllerFactory factory = new TempControllerFactory();
            Type ct = factory.GetTypeOfController(new RequestContext(httpContext, data), controllerName);
            if (ct != null)
            {
                ReflectedControllerDescriptor ds = new ReflectedControllerDescriptor(ct);
                ControllerContext cc = new ControllerContext { RequestContext = new RequestContext(httpContext, data) };
                var act = ds.FindAction(cc, actionName);
                if (act != null)
                {
                    return data;
                }
                //int cnt = ct.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).Count(x => string.Compare(x.Name, actionName, true) == 0 && typeof(ActionResult).IsAssignableFrom(x.ReturnType));
                //if (cnt > 0)
                //{
                //    return data;
                //}
            }
            string[] exts = new string[] { ".cshtml", ".vbhtml", ".aspx" };
            string fileNameWithoutExt = Path.Combine(Plugin.GetPluginFolder(meta.UniqueName), "Views", controllerName, actionName);
            foreach (string ext in exts)
            {
                string file = fileNameWithoutExt + ext;
                if (File.Exists(file))
                {
                    data.DataTokens["Namespaces"] = new string[] { "MVCPlugin.Utility" };
                    data.Values["UseCommonController"] = "1";
                    data.Values["action"] = "Common";
                    data.Values["viewPath"] = string.Concat("~/", Plugin.BASE_FOLDER_NAME, "/", Plugin.GetValidPath(meta.UniqueName), "/Views/", controllerName, "/", actionName + ext);
                    return data;
                }
            }
            return null;
        }

        private class TempControllerFactory : DefaultControllerFactory
        {
            public Type GetTypeOfController(RequestContext requestContext, string controllerName)
            {
                return base.GetControllerType(requestContext, controllerName);
            }
        }
    }
}
